`timescale 1ns/100ps

`include "sim_glb.sv"

module tc;

localparam          CLK_PRD                 = 5;
localparam          DW                      = 8;
localparam          TYPE                    = "CRC_32";     // "CRC_CCITT" "CRC_32"
localparam          FIRST                   = "LSB";        // bit[0] is transmitted first in serial mode
localparam          CW                      = 32;

reg                                         rst_n;
reg                                         clk;

reg                                         tx_vld;
reg                 [DW-1:0]                tx_dat;

reg                 [CW-1:0]                crc;
wire                [CW-1:0]                crc_c;

initial begin:CRG
    rst_n=1'b0;
    clk=1'b0;

    fork
        rst_n=#100.5 1'b1;
        forever clk=#CLK_PRD ~clk;
    join
end

RGRS_MNG    rgrs;
initial begin:REGRESS
    rgrs = new("tc_crc", 1);

    rgrs.wait_chks_done(100_000_000);
end

initial begin:GEN_CELL
    tx_vld <=`U_DLY 1'b0;
    tx_dat <=`U_DLY {DW{1'b0}};

    @(posedge rst_n);
    @(posedge clk);

    crc <=`U_DLY 32'hFFFFFFFF;
    @(posedge clk);
    repeat(29) begin
             //len  dat
        tx_pkt( 12, 96'h5935FB5E14B38F6B4723D7BE);
    end
    @(posedge clk);
    if ((~crc)!=32'hEFAAE02F) begin
        $error("[ERROR] MAC CRC32 is wrong!");
    end

    @(posedge clk);
    @(posedge clk);
    @(posedge clk);
    rgrs.one_chk_done("gen is done.");
end

crc_calc #(
        .DW                             (DW                             ),
        .TYPE                           ("CRC_32"                       ),	// "CRC_CCITT" "CRC_32"
        .FIRST                          ("LSB"                          ),	// bit[0] is transmitted first in serial mode
        .CW                             (CW                             )
) u_crc_calc ( 
        .dat_cur                        (tx_dat                         ),	// current data
        .crc_cur                        (crc                            ),	// current crc
        .crc_nxt                        (crc_c                          )	// next crc
);

always@(posedge clk or negedge rst_n) begin
    if (rst_n==1'b0) begin
        crc <=`U_DLY 32'h00000000;
    end else begin
        if (tx_vld==1'b1) begin
            crc <=`U_DLY crc_c;
        end
    end
end

task tx_pkt;
    input integer           len;
    input [64*8-1:0]        dat;

    integer i;
    begin
        for(i=1; i<=len; i=i+1) begin
            tx_vld <=`U_DLY 1'b1;
            tx_dat <=`U_DLY dat[0+:DW];
            dat = dat>>DW;
            @(posedge clk);
        end
        tx_vld <=`U_DLY 1'b0;
    end
endtask

endmodule

